# ZPsycopgDA/pool.py - ZPsycopgDA Zope product: connection pooling
#
# Copyright (C) 2004 Federico Di Gregorio <fog@initd.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any later
# version.
#
# Or, at your option this program (ZPsycopgDA) can be distributed under the
# Zope Public License (ZPL) Version 1.0, as published on the Zope web site,
# http://www.zope.org/Resources/ZPL.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY
# or FITNESS FOR A PARTICULAR PURPOSE.
#
# See the LICENSE file for details.
"""
 This file was changed to work with DCOracle2
 This implementation uses different pool and 
 this is not a pool of database connections but
 a pool of ResourceManagers (that have dco2 
 connection inside)
"""

import threading
from da_simple_pool import DASimplePool
import time
import logging
logger = logging.getLogger('DCOracle2-pool.py')

_connections_pool = {}
_connections_lock = threading.Lock()

def getpool(dsn, unique_id, create=True, factory=None, poolsize=1):
    """ Create a pool of connections for specific dsn
    """
    pool_id = dsn + '_' + unique_id
    pool_id_repeats = pool_id + '_cl_repeats'
    
    _connections_lock.acquire()    
    try:
        if not _connections_pool.has_key(pool_id) and create:
            try:
                _connections_pool[pool_id] = \
                    DASimplePool(factory, dsn, unique_id, min_size=poolsize)
                _connections_pool[pool_id_repeats] = 0                    
            except Exception, err:
                logger.error('getpool: %s' % err, exc_info=True)
                raise
    finally:
        _connections_lock.release()
    return _connections_pool.get(pool_id, None)

def flushpool(dsn, unique_id):
    """ Flush the pool of connections.
    """
    pool_id = dsn + '_' + unique_id
    pool_id_repeats = pool_id + '_cl_repeats'
    
    while 1:
        _connections_lock.acquire()
        try:
            if pool_id in _connections_pool.keys():
                closed = _connections_pool[pool_id].dispose()
                if closed == 1 or _connections_pool[pool_id_repeats] > 10:
                    del _connections_pool[pool_id]
                    closed = 1
                    if _connections_pool[pool_id_repeats] > 10:
                        logger.error('Not all connections closed cleanly!' \
                                   +' Pool closing forced!')
                        del _connections_pool[pool_id_repeats]
                    break
                _connections_pool[pool_id_repeats] += 1
            else:
                break
        finally:
            _connections_lock.release()
        logger.info( 'Flushpool - waiting for other threads ' \
                    +'to put connections back to the pool')
        time.sleep(1)
            

def getconn(dsn, unique_id, create=True, factory=None, poolsize=1):
    return getpool(dsn, unique_id, create=create, factory=factory, \
                   poolsize=poolsize).getconn()    

def putconn(dsn, unique_id, close=False):
    pl = getpool(dsn, unique_id, create=False)
    if pl:
        pl.putconn(close=close)
    
def get_pool_size(dsn, unique_id):
    pl = getpool(dsn, unique_id, create=False)
    if pl:
        return pl.get_pool_size()
    return 0